package actions

import (
	"context"
	"fmt"
	"time"

	"github.com/google/uuid"
	"github.com/sirupsen/logrus"

	"xagent/internal/actor"
	proto "xagent/proto/v1"
)

// WriteCodeAction implements code writing functionality
type WriteCodeAction struct {
	*actor.BaseAction
	logger *logrus.Logger
}

func NewWriteCodeAction() *WriteCodeAction {
	return &WriteCodeAction{
		BaseAction: actor.NewBaseAction("write_code"),
		logger:     logrus.New(),
	}
}

func (a *WriteCodeAction) Run(ctx context.Context, input interface{}) (*proto.AgentMessage, error) {
	task, ok := input.(*proto.Task)
	if !ok {
		return nil, fmt.Errorf("invalid input type")
	}

	// Get code specification from task
	spec := task.Description
	if spec == "" {
		return nil, fmt.Errorf("code specification is empty")
	}

	// Record start time
	startTime := time.Now()

	// Add metadata
	a.AddMetadata("task_id", task.Id)
	a.AddMetadata("start_time", startTime)

	// Generate code implementation
	codeResult := &CodeResult{
		ID:          uuid.NewString(),
		TaskID:      task.Id,
		Code:        "// Generated code\n",
		Language:    "go",
		StartTime:   startTime,
		EndTime:     time.Now(),
		Status:      "COMPLETED",
		TestsPassed: true,
		Metrics: map[string]interface{}{
			"lines_of_code": 100,
			"complexity":    5,
			"duration":      time.Since(startTime).String(),
		},
	}

	return &proto.AgentMessage{
		Id:   uuid.NewString(),
		Type: proto.MessageType_MESSAGE_TYPE_RESPONSE,
		Content: &proto.AgentMessage_Message{
			Message: fmt.Sprintf("Code generated successfully: %s", codeResult.ID),
		},
		Metadata: map[string]string{
			"code_id":    codeResult.ID,
			"language":   codeResult.Language,
			"status":     codeResult.Status,
			"duration":   codeResult.Metrics["duration"].(string),
			"lines":      fmt.Sprintf("%d", codeResult.Metrics["lines_of_code"]),
			"complexity": fmt.Sprintf("%d", codeResult.Metrics["complexity"]),
			"task_id":    task.Id,
		},
	}, nil
}

// ReviewCodeAction implements code review functionality
type ReviewCodeAction struct {
	*actor.BaseAction
	logger *logrus.Logger
}

func NewReviewCodeAction() *ReviewCodeAction {
	return &ReviewCodeAction{
		BaseAction: actor.NewBaseAction("review_code"),
		logger:     logrus.New(),
	}
}

func (a *ReviewCodeAction) Run(ctx context.Context, input interface{}) (*proto.AgentMessage, error) {
	task, ok := input.(*proto.Task)
	if !ok {
		return nil, fmt.Errorf("invalid input type")
	}

	// Get code to review from task metadata
	codeID, ok := task.Metadata["code_id"]
	if !ok {
		return nil, fmt.Errorf("code ID not provided")
	}

	startTime := time.Now()

	// Record review activity
	reviewResult := &CodeReviewResult{
		ID:        uuid.NewString(),
		CodeID:    codeID,
		TaskID:    task.Id,
		StartTime: startTime,
		EndTime:   time.Now(),
		Status:    "APPROVED",
		Comments: []ReviewComment{
			{
				ID:        uuid.NewString(),
				Line:      10,
				Content:   "Good implementation",
				Type:      "POSITIVE",
				Severity:  "INFO",
				CreatedAt: time.Now(),
			},
		},
		Metrics: map[string]interface{}{
			"comments_count": 1,
			"duration":       time.Since(startTime).String(),
		},
	}

	return &proto.AgentMessage{
		Id:   uuid.NewString(),
		Type: proto.MessageType_MESSAGE_TYPE_RESPONSE,
		Content: &proto.AgentMessage_Message{
			Message: fmt.Sprintf("Code review completed: %s, Status: %s", reviewResult.ID, reviewResult.Status),
		},
		Metadata: map[string]string{
			"review_id":      reviewResult.ID,
			"code_id":        reviewResult.CodeID,
			"status":         reviewResult.Status,
			"duration":       reviewResult.Metrics["duration"].(string),
			"comments_count": fmt.Sprintf("%d", reviewResult.Metrics["comments_count"]),
			"task_id":        task.Id,
		},
	}, nil
}

// CodeResult represents the result of code generation
type CodeResult struct {
	ID          string
	TaskID      string
	Code        string
	Language    string
	StartTime   time.Time
	EndTime     time.Time
	Status      string
	TestsPassed bool
	Metrics     map[string]interface{}
}

// CodeReviewResult represents the result of a code review
type CodeReviewResult struct {
	ID        string
	CodeID    string
	TaskID    string
	StartTime time.Time
	EndTime   time.Time
	Status    string
	Comments  []ReviewComment
	Metrics   map[string]interface{}
}

// ReviewComment represents a code review comment
type ReviewComment struct {
	ID        string
	Line      int
	Content   string
	Type      string
	Severity  string
	CreatedAt time.Time
}
